package elephant.rpc.server;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import elephant.rpc.network.netty.NettyServerService;
import elephant.rpc.server.core.LocalProxyFactory;
import elephant.rpc.server.core.NetworkService;
import elephant.rpc.server.core.PerformMonitor;
import elephant.rpc.server.service.MethodStub;
import elephant.rpc.server.service.RPCServiceInterceptor;
import elephant.rpc.server.service.RPCServiceManager;
import elephant.rpc.server.session.RPCSessionManager;
import elephant.rpc.threadpool.ThreadPoolManager;
import elephant.utils.ObjectPrinter;

/**
 * 
 * @author skydu
 *
 */
public class RPCServer{
	//
	private static Logger logger=LoggerFactory.getLogger(RPCServer.class);
	//
	public static final String CODEC_TYPE_FASTJSON="fastjson";
	public static final String CODEC_TYPE_JDK="jdk";
	//
	public static String codecType=CODEC_TYPE_FASTJSON;
	public static int maxMsgLength=1024*1024*10;//10m
	//
	private PerformMonitor performMonitor;
	private ThreadPoolManager threadPoolManager;
	private NetworkService networkService;
	private RPCSessionManager sessionManager;
	private RPCServiceManager serviceManager;
	private LocalProxyFactory localProxyFactory;
	private ClassLoader contextClassLoader;
	private int port;
	//
	public RPCServer(){
		performMonitor=new PerformMonitor();
		threadPoolManager=new ThreadPoolManager(contextClassLoader);
		sessionManager=new RPCSessionManager();
		serviceManager=new RPCServiceManager();
		networkService=new NettyServerService(this);
		localProxyFactory=new LocalProxyFactory(serviceManager);
	}
	//
	public void init() throws Exception {
		if(logger.isInfoEnabled()){
			logger.info(getClass().getSimpleName()+" init");
		}
		threadPoolManager.init();
		networkService.init();
	}
	//
	public void start() throws Exception {
		if(logger.isInfoEnabled()){
			logger.info(getClass().getSimpleName()+" start");
		}
		threadPoolManager.start();
		networkService.start();
		if(logger.isInfoEnabled()){
			logger.info(dump());
		}
	}
	//
	public void stop() throws Exception {
		if(logger.isInfoEnabled()){
			logger.info(getClass().getSimpleName()+" stop");
		}
		networkService.stop();
	}
	//
	public void registerService(Class<?> interfaceClass,Object service){
		serviceManager.registerService(interfaceClass, service);
	}
	//
	public Object getService(Class<?> interfaceClass){ 
		return serviceManager.getService(interfaceClass);
	}
	//
	public <T> T createLocalService(Class<T> interfaceClass){
		return localProxyFactory.getLocalService(interfaceClass);
	}
	//
	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port=port;
	}
	
	/**
	 * @return the codecType
	 */
	public String getCodecType() {
		return codecType;
	}
	/**
	 * @param codecType the codecType to set
	 */
	public void setCodecType(String codecType) {
		RPCServer.codecType = codecType;
	}
	/**
	 * @return the performMonitor
	 */
	public PerformMonitor getPerformMonitor() {
		return performMonitor;
	}
	/**
	 * @param performMonitor the performMonitor to set
	 */
	public void setPerformMonitor(PerformMonitor performMonitor) {
		this.performMonitor = performMonitor;
	}
	//
	/**
	 * @return the sessionManager
	 */
	public RPCSessionManager getSessionManager() {
		return sessionManager;
	}
	/**
	 * @param sessionManager the sessionManager to set
	 */
	public void setSessionManager(RPCSessionManager sessionManager) {
		this.sessionManager = sessionManager;
	}
	/**
	 * @return the threadPoolManager
	 */
	public ThreadPoolManager getThreadPoolManager() {
		return threadPoolManager;
	}
	/**
	 * @param threadPoolManager the threadPoolManager to set
	 */
	public void setThreadPoolManager(ThreadPoolManager threadPoolManager) {
		this.threadPoolManager = threadPoolManager;
	}
	
	/**
	 * @return the serviceManager
	 */
	public RPCServiceManager getServiceManager() {
		return serviceManager;
	}
	/**
	 * @param serviceManager the serviceManager to set
	 */
	public void setServiceManager(RPCServiceManager serviceManager) {
		this.serviceManager = serviceManager;
	}
	//
	/**
	 * @param interceptor the interceptor to set
	 */
	public void setRPCServiceInterceptor(RPCServiceInterceptor interceptor) {
		this.serviceManager.setInterceptor(interceptor);
	}
	/**
	 * @return the networkService
	 */
	public NetworkService getNetworkService() {
		return networkService;
	}
	/**
	 * @param networkService the networkService to set
	 */
	public void setNetworkService(NetworkService networkService) {
		this.networkService = networkService;
	}
	/**
	 * @return the localProxyFactory
	 */
	public LocalProxyFactory getLocalProxyFactory() {
		return localProxyFactory;
	}
	/**
	 * @param localProxyFactory the localProxyFactory to set
	 */
	public void setLocalProxyFactory(LocalProxyFactory localProxyFactory) {
		this.localProxyFactory = localProxyFactory;
	}
	/**
	 * @return the contextClassLoader
	 */
	public ClassLoader getContextClassLoader() {
		return contextClassLoader;
	}
	/**
	 * @param contextClassLoader the contextClassLoader to set
	 */
	public void setContextClassLoader(ClassLoader contextClassLoader) {
		this.contextClassLoader = contextClassLoader;
	}
	/**
	 * @return the maxMsgLength
	 */
	public static int getMaxMsgLength() {
		return maxMsgLength;
	}
	/**
	 * @param maxMsgLength the maxMsgLength to set
	 */
	public static void setMaxMsgLength(int maxMsgLength) {
		RPCServer.maxMsgLength = maxMsgLength;
	}
	//
	public String dump() {
		ObjectPrinter op=new ObjectPrinter();
		op.section(getClass().getSimpleName());
		op.print("port",port);
		op.print("codecType",codecType);
		op.print("contextClassLoader",contextClassLoader);
		op.print("maxMsgLength",maxMsgLength);
		op.secondSection("service");
		int index=1;
		for(MethodStub stub:serviceManager.getMethodNames()){
			op.print(index++,stub.methodName);
		}
		return op.toString();
	}
}
